home *** CD-ROM | disk | FTP | other *** search
- UNIT Globals;
- {-------------------------------------------}
- (*
- ©1988 by Steve Seaquist. All rights reserved.
- Used by permission. Use at your own risk.
- No warranty is expressed or implied.
-
- This Macintosh virus-detecting program was
- originally published and explained in the
- February 1989 issue of MacTutor magazine.
- Some aspects of its design are important to
- security, and it uses some unusual
- techniques, so please read the article.
- *)
- {-------------------------------------------}
- INTERFACE
- USES
- MacIntf,BitProcs;
-
- CONST
- {---- Low Mem Globals ----}
- kCurApName = $910;
- kCurApRefNum = $900;
- kBootDrive = $210;
- kResLoad = $A5E;
- kScrDmpEnb = $2F8;
- kSFCBLen = $3F6;
- kSPConfig = $1FB;
- kSysMap = $A58;
- kSysResName = $AD8;
- {---- Other constants ----}
- kIOBufferSize = 10000;
- kProcessSelf = FALSE;
- kRsrcHdlValid = 9876543;
- kRsrcIsInitd = 3456789;
- kZeroOutVirs = TRUE;
-
- TYPE
- TCountsPtr = ^TCountsRec;
- TCountsRec =
- RECORD
- fDeleted: LONGINT;
- fExamined: LONGINT;
- fFiles: LONGINT;
- fInfected: LONGINT;
- fRemoved: LONGINT;
- fResources: LONGINT;
- END;
-
- TFeedbackPtr = ^TFeedbackRec;
- TFeedbackRec =
- PACKED RECORD
- fWroteDirname: BOOLEAN;
- fWroteFilename: BOOLEAN;
- END;
-
- TJTEHdl = ^TJTEPtr;
- TJTEPtr = ^TJTERec;
- TJTERec =
- RECORD
- fOffset: INTEGER;
- fSkip3F3C: INTEGER;
- fSegId: INTEGER;
- fSkipA9F0: INTEGER;
- END;
-
- TJTHdl = ^TJTPtr;
- TJTPtr = ^TJTRec;
- TJTRec =
- RECORD
- fAboveA5Size: LONGINT;
- fBelowA5Size: LONGINT;
- fNbrBytesInTable: LONGINT;
- fTableOffset: LONGINT;
- fJTEntry:
- ARRAY [1..1] OF TJTERec;
- END;
-
- TLoaded =
- (eNotYet,eAlreadyLoaded,eWeLoadedIt);
-
- TMainItem =
- (eNotADlogItem,
- eDirs,eDiry,eEvery,eFiles,eQuit,
- eAwait,eBeeps,eFgPr,eFgPrC,
- eLList,eRmVir,eTrace,
- eMain,eOpts,eScOW,
- eDBtn);
- TMainOpt =
- ARRAY [eAwait..eTrace] OF BOOLEAN;
-
- TPaocRec =
- PACKED ARRAY[1..1] OF CHAR;
- TResIdOrIndex = (ResId,Index);
-
- TRsrcPtr = ^TRsrcRec;
- TRsrcRec =
- RECORD
- fFlag: LONGINT;
- fHdl: Handle;
- fInfected: BOOLEAN;
- fKnown: BOOLEAN;
- fLoaded: TLoaded;
- fResAttrs: INTEGER;
- fResId: INTEGER;
- fResType: ResType;
- fSize: Size;
- fState: SignedByte;
- END;
-
- TScoresHdl = ^TScoresPtr;
- TScoresPtr = ^TScoresRec;
- TScoresRec =
- RECORD
- fOffsetToFirstJTE:INTEGER;
- fNbrJTEsForRsrc: INTEGER;
- fOldJTE: TJTERec;
- END;
-
- TWordHdl = ^TWordPtr;
- TWordPtr = ^INTEGER;
-
- VAR
- gAAGlobals: SignedByte;
- gAbortPatrol: BOOLEAN;
- gActiveSelf: BOOLEAN;
- gActiveSys: BOOLEAN;
- gCode0: TRsrcRec;
- gCounts: TCountsRec;
- gCurrDInfo: DInfo;
- gCurrDirId: LONGINT;
- gCurrDirname: Str255;
- gCurrEOF: LONGINT;
- gCurrIOBuffer: Ptr;
- gCurrFileDeleted: BOOLEAN;
- gCurrFilename: Str255;
- gCurrFInfo: FInfo;
- gCurrIndex: INTEGER;
- gCurrRefNum: INTEGER;
- gCurrRsrc: TRsrcRec;
- gCurrVRefNum: INTEGER;
- gCurrWDRefNum: INTEGER;
- gDateTimeRec: DateTimeRec;
- gDisabled: TMainOpt;
- gDlogPtr: DialogPtr;
- gError: OSErr;
- gEvt: EventRecord;
- gEvtMask: INTEGER;
- gFgPrTitle: Str255;
- gGrafPtr: GrafPtr;
- gHFS: BOOLEAN;
- gInd: STRING[10];
- gInfected: BOOLEAN;
- gInfectedWritten: BOOLEAN;
- gOption: TMainOpt;
- gPgmrname: Str255;
- gReportFlags: TFeedbackRec;
- gScreenFlags: TFeedbackRec;
- gSecsBegins: LONGINT;
- gSecsEnds: LONGINT;
- gSFGetPt: Point;
- gSFPutPt: Point;
- gSFRep: SFReply;
- gTotals: TCountsRec;
- gZZGlobals: SignedByte;
-
- FUNCTION Code0IsValid
- : BOOLEAN;
- PROCEDURE CommentBegins;
- PROCEDURE CommentFgPrRsrc
- (pRsrcPtr: TRsrcPtr);
- PROCEDURE CommentRsrcBegins
- (pRsrcPtr: TRsrcPtr);
- PROCEDURE DirectoryBegins;
- PROCEDURE DirectoryEnds;
- PROCEDURE ErrorBegins
- (pStr: Str255);
- PROCEDURE ErrorEnds
- (pBeeps: INTEGER);
- PROCEDURE ErrorOSErr
- (pStr: Str255);
- PROCEDURE GetRsrc
- (pRsrcPtr: TRsrcPtr;
- pResType: ResType;
- pInt: INTEGER;
- pIntIs: TResIdOrIndex);
- PROCEDURE InitGlobals;
- PROCEDURE InitRsrc
- (pRsrcPtr: TRsrcPtr);
- FUNCTION JTEIsValid
- (pJTEPtr: TJTEPtr)
- : BOOLEAN;
- PROCEDURE ListCounts
- (pPtr: TCountsPtr);
- PROCEDURE LookForKnownViruses;
- PROCEDURE PauseBriefly;
- PROCEDURE PatrolBegins;
- PROCEDURE PatrolEnds;
- PROCEDURE ProcessCurrRsrc;
- PROCEDURE ProcessFile;
- PROCEDURE ReleaseRsrc
- (pRsrcPtr: TRsrcPtr);
- PROCEDURE ShortHexDump
- (pPtr: Ptr;
- pNbrBytes: SignedByte);
- PROCEDURE Trace
- (pStr: Str255);
- PROCEDURE TraceNbr
- (pStr: Str255;
- pNbr: LONGINT);
- PROCEDURE ZeroOut
- (pStart: Ptr;
- pCount: Size);
- PROCEDURE ZeroOutRange
- (p1: Ptr;
- p2: Ptr);
-
- {*******************************************}
- IMPLEMENTATION
- {$R-}
-
- PROCEDURE ExitSecurityPatrol; EXTERNAL;
- PROCEDURE Wryte
- (pStr: Str255); EXTERNAL;
- PROCEDURE WryteChar
- (pChar: CHAR); EXTERNAL;
- PROCEDURE WryteEoln; EXTERNAL;
- PROCEDURE WryteFilename; EXTERNAL;
- PROCEDURE WryteFilenameToScreenOnlyForNow;
- EXTERNAL;
- PROCEDURE WryteLn
- (pStr: Str255); EXTERNAL;
- PROCEDURE WryteNbr
- (pNbr: LONGINT;
- pNbrDigits:INTEGER); EXTERNAL;
- PROCEDURE WryteType
- (pType: ResType); EXTERNAL;
-
- PROCEDURE CallProcPtr
- (pProcPtr: ProcPtr);
- INLINE
- $205F, { MOVE.L (A7)+,A0 }
- $4E90; { JSR (A0) }
-
- PROCEDURE ErrorInfected
- (pStr: Str255); FORWARD;
- PROCEDURE ErrorMsg
- (pStr: Str255;
- pBeeps: INTEGER); FORWARD;
- FUNCTION FixedCode0
- (pJTPtr: TJTEPtr)
- : BOOLEAN; FORWARD;
- PROCEDURE ProcessRsrcs
- (pResType: ResType;
- pProcPtr: ProcPtr); FORWARD;
- FUNCTION RemovedRsrc
- (pRsrcPtr: TRsrcPtr)
- : BOOLEAN; FORWARD;
- PROCEDURE TraceRsrc
- (pStr: Str255;
- pRsrcPtr: TRsrcPtr); FORWARD;
-
- {$S Fingerprint}
- {$I Fingerprint.ipas }
- {$S Globals}
- {-------------------------------------------}
- PROCEDURE AbortPatrolIfCmdPeriodPressed;
- BEGIN
- WHILE GetNextEvent(gEvtMask,gEvt) DO
- WITH gEvt DO
- IF (what = nullEvent) THEN
- LEAVE
- ELSE IF (what = keyDown) THEN
- IF (BAnd(modifiers,cmdKey)=cmdKey)
- AND (BAnd(message,charCodeMask)=$2E)
- THEN
- BEGIN
- gAbortPatrol := TRUE;
- WryteLn('Patrol aborted');
- LEAVE;
- END;
- END;
- {-------------------------------------------}
- PROCEDURE AwaitKeypress;
- BEGIN
- WHILE TRUE DO
- BEGIN
- IF NOT(GetNextEvent(gEvtMask,gEvt)) THEN
- CYCLE;
- WITH gEvt DO
- IF (what = keyDown) THEN
- BEGIN
- IF (BAnd(modifiers,cmdKey)=cmdKey)
- AND (BAnd(message,charCodeMask)=$2E)
- THEN
- BEGIN
- gAbortPatrol := TRUE;
- WryteLn('Patrol aborted');
- END;
- LEAVE;
- END;
- END;
- END;
- {-------------------------------------------}
- FUNCTION Code0IsValid
- : BOOLEAN;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('Code0IsValid');
- WITH TJTHdl(gCode0.fHdl)^^ DO
- Code0IsValid :=
- (gCode0.fSize >= 24) AND
- (fAboveA5Size >= 40) AND
- (fNbrBytesInTable >= 8) AND
- (fTableOffset = 32) AND
- (fAboveA5Size = fNbrBytesInTable+32) AND
- ((fNbrBytesInTable MOD 8) = 0);
- END;
- {-------------------------------------------}
- PROCEDURE CommentBegins;
- BEGIN
- Wryte(gInd);
- Wryte(gInd);
- Wryte(gInd);
- END;
- {-------------------------------------------}
- PROCEDURE CommentRsrcBegins
- (pRsrcPtr: TRsrcPtr);
- BEGIN
- CommentBegins;
- WITH pRsrcPtr^ DO
- BEGIN
- WryteType(fResType);
- WryteNbr (fResId,7);
- Wryte (' (');
- ShortHexDump(Ptr(ORD4(@fResAttrs)+1),1);
- WryteChar(')');
- END;
- END;
- {-------------------------------------------}
- PROCEDURE CountInfected;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('CountInfected');
- INC(gCounts.fInfected);
- INC(gTotals.fInfected);
- END;
- {-------------------------------------------}
- PROCEDURE DirectoryBegins;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('DirectoryBegins');
- gReportFlags.fWroteDirname := FALSE;
- gScreenFlags.fWroteDirname := FALSE;
- END;
- {-------------------------------------------}
- PROCEDURE DirectoryEnds;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('DirectoryEnds');
- (*
- Wryte ('End of ');
- WryteLn(gCurrDirname);
- *)
- END;
- {-------------------------------------------}
- FUNCTION Disinfected_nVIR
- : BOOLEAN;
- VAR
- snVIR2: TRsrcRec;
- sCodeGone: BOOLEAN;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('Disinfected_nVIR');
- Disinfected_nVIR := FALSE;
- InitRsrc(@snVIR2);
- GetRsrc (@snVIR2,'nVIR',2,ResId);
- WITH snVIR2 DO
- BEGIN
- IF (fFlag <> kRsrcHdlValid) THEN
- BEGIN
- ErrorInfected('No nVIR 2!');
- ReleaseRsrc(@gCurrRsrc);
- EXIT(Disinfected_nVIR);
- END;
- IF (fSize < 8) THEN
- BEGIN
- ErrorInfected('Too small nVIR 2!');
- ReleaseRsrc(@gCurrRsrc);
- ReleaseRsrc(@snVIR2);
- EXIT(Disinfected_nVIR);
- END;
- MoveHHi(fHdl);
- HLock (fHdl);
- IF NOT(FixedCode0(TJTEPtr(fHdl^))) THEN
- BEGIN
- ReleaseRsrc(@gCurrRsrc);
- ReleaseRsrc(@snVIR2);
- EXIT(Disinfected_nVIR);
- END;
- Disinfected_nVIR := TRUE;
- sCodeGone := RemovedRsrc(@gCurrRsrc);
- ReleaseRsrc(@snVIR2);
- ProcessRsrcs('nVIR',@ProcessRemoveRsrc);
- IF sCodeGone
- AND (Count1Resources('nVIR') = 0) THEN
- ErrorMsg('nVIR removed',0)
- ELSE
- BEGIN
- ErrorMsg('nVIR “disinfected”:',0);
- CommentBegins;
- Wryte ('All of its resources are now ');
- Wryte ('harmless, but some were not ');
- WryteLn('removed, for some reason.');
- END;
- END;
- END;
- {-------------------------------------------}
- FUNCTION Disinfected_Scores
- : BOOLEAN;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('Disinfected_Scores');
- Disinfected_Scores := FALSE;
- WITH gCurrRsrc DO
- BEGIN
- MoveHHi(fHdl);
- HLock (fHdl);
- WITH TScoresHdl(fHdl)^^ DO
- IF NOT(FixedCode0(@fOldJTE)) THEN
- BEGIN
- ReleaseRsrc(@gCurrRsrc);
- EXIT(Disinfected_Scores);
- END;
- Disinfected_Scores := TRUE;
- IF RemovedRsrc(@gCurrRsrc) THEN
- ErrorMsg('Scores removed',0)
- ELSE
- ErrorMsg('Scores disinfected',0);
- END;
- END;
- {-------------------------------------------}
- PROCEDURE ErrorBegins
- (pStr: Str255);
- BEGIN
- WryteFilename;
- Wryte (gInd);
- Wryte (gInd);
- Wryte (pStr);
- END;
- {-------------------------------------------}
- PROCEDURE ErrorEnds
- (pBeeps: INTEGER);
- VAR
- i: INTEGER;
- sBeeps: INTEGER;
- BEGIN
- IF gOption[eBeeps] THEN
- BEGIN
- IF (pBeeps > 4) THEN
- sBeeps := 4
- ELSE
- sBeeps := pBeeps;
- FOR i := 1 TO sBeeps DO
- SysBeep(3);
- END;
- IF gOption[eAwait] THEN
- BEGIN
- WryteLn(' (WAITING ON KEY PRESS)');
- AwaitKeypress;
- END
- ELSE
- WryteEoln;
- END;
- {-------------------------------------------}
- PROCEDURE ErrorInfected
- (pStr: Str255);
- BEGIN
- IF NOT(gInfectedWritten) THEN
- BEGIN
- ErrorBegins('**!INFECTED!** ');
- WryteEoln;
- gInfectedWritten := TRUE;
- END;
- IF (pStr <> '') THEN
- BEGIN
- CommentBegins;
- Wryte(pStr);
- ErrorEnds(3);
- END;
- END;
- {-------------------------------------------}
- PROCEDURE ErrorMsg
- (pStr: Str255;
- pBeeps: INTEGER);
- BEGIN
- ErrorBegins(pStr);
- ErrorEnds(pBeeps);
- END;
- {-------------------------------------------}
- PROCEDURE ErrorOSErr
- (pStr: Str255);
- BEGIN
- IF (pStr <> '') THEN
- BEGIN
- ErrorBegins(pStr);
- WryteEoln;
- END;
- CommentBegins;
- Wryte ('OSErr code = ');
- WryteNbr(gError,1);
- ErrorEnds(2);
- END;
- {-------------------------------------------}
- FUNCTION FixedCode0
- (pJTPtr: TJTEPtr)
- : BOOLEAN;
- BEGIN
- FixedCode0 := FALSE;
- IF gOption[eTrace] THEN
- Trace('FixedCode0');
- IF NOT(JTEIsValid(pJTPtr)) THEN
- BEGIN
- ErrorInfected('Bad Jump Table Entry!');
- EXIT(FixedCode0);
- END;
- IF NOT(gOption[eRmVir]) THEN
- BEGIN
- ErrorInfected('Remove option off');
- CommentBegins;
- WITH pJTPtr^ DO
- BEGIN
- Wryte ('Jumps to ');
- WryteNbr(fOffset,1);
- Wryte (' of CODE ');
- WryteNbr(fSegId,1);
- WryteEoln;
- END;
- ErrorMsg('Not removed',1);
- EXIT(FixedCode0);
- END;
- WITH gCode0 DO
- BEGIN
- IF gOption[eTrace] THEN
- BEGIN
- Trace('About to restore CODE 0');
- AbortPatrolIfCmdPeriodPressed;
- IF gAbortPatrol THEN
- EXIT(FixedCode0);
- END;
- TJTHdl(fHdl)^^.fJTEntry[1] := pJTPtr^;
- IF (BAnd(fResAttrs,resProtected) <> 0)
- AND (fResAttrs <> -1) THEN
- BEGIN
- SetResAttrs(fHdl,0);
- ChangedResource(fHdl);
- gError := ResError;
- SetResAttrs(fHdl,fResAttrs);
- END
- ELSE
- BEGIN
- ChangedResource(fHdl);
- gError := ResError;
- END;
- IF (gError <> NoErr) THEN
- BEGIN
- ErrorInfected('CODE 0 unchanged!');
- IF (gError = wPrErr) THEN
- ErrorMsg('Disk is locked',0)
- ELSE
- ErrorOSErr('');
- gError := 0;
- EXIT(FixedCode0);
- END;
- WriteResource(fHdl);
- gError := ResError;
- IF (gError <> NoErr) THEN
- BEGIN
- ErrorInfected('CODE 0 unwritten!');
- ErrorOSErr('');
- EXIT(FixedCode0);
- END;
- END;
- FixedCode0 := TRUE;
- END;
- {-------------------------------------------}
- PROCEDURE GetRsrc
- (pRsrcPtr: TRsrcPtr;
- pResType: ResType;
- pInt: INTEGER;
- pIntIs: TResIdOrIndex);
- VAR
- sName: Str255;
- sResLoad: BOOLEAN;
- {----------------------}
- PROCEDURE CommentWhich;
- BEGIN
- CommentBegins;
- WryteType(pResType);
- WryteChar(' ');
- WryteNbr (pInt,1);
- IF (pIntIs = Index) THEN
- Wryte (' (indexed)');
- WryteEoln;
- END;
- {----------------------}
- BEGIN
- WITH pRsrcPtr^ DO
- BEGIN
- IF (fFlag <> kRsrcIsInitd) THEN
- BEGIN
- ErrorMsg('Logic error using GetRsrc',4);
- AwaitKeypress;
- ExitSecurityPatrol;
- END;
- fResType := pResType;
- fResId := pInt;
- sResLoad := (TWordPtr(kResLoad)^ <> 0);
- IF (gActiveSelf OR gActiveSys) THEN
- SetResLoad(FALSE);
- IF (pIntIs = Index) THEN
- BEGIN
- IF gOption[eTrace] THEN
- TraceRsrc('About to get ind',pRsrcPtr);
- fHdl := Get1IndResource(pResType,pInt);
- END
- ELSE
- BEGIN
- IF gOption[eTrace] THEN
- TraceRsrc('About to get',pRsrcPtr);
- fHdl := Get1Resource(pResType,pInt);
- END;
- IF sResLoad THEN
- BEGIN
- IF (gActiveSelf OR gActiveSys) THEN
- SetResLoad(TRUE);
- IF (fHdl = NIL)
- OR (ORD4(fHdl) = -1) THEN
- BEGIN
- gError := ResError;
- ErrorOSErr('Couldn’t get resource');
- CommentWhich;
- InitRsrc(pRsrcPtr);
- EXIT(GetRsrc);
- END;
- fFlag := kRsrcHdlValid;
- fResAttrs := GetResAttrs(fHdl);
- IF (ResError <> NoErr) THEN
- fResAttrs := -1;
- IF (fHdl^ = NIL) THEN
- BEGIN
- LoadResource(fHdl);
- fLoaded := eWeLoadedIt;
- IF gOption[eTrace] THEN
- Trace('We loaded it');
- END
- ELSE
- BEGIN
- fLoaded := eAlreadyLoaded;
- IF gOption[eTrace] THEN
- Trace('Already loaded');
- END;
- IF (fHdl^ = NIL) THEN
- BEGIN
- gError := ResError;
- IF (gError <> NoErr) THEN
- BEGIN
- ErrorMsg('Couldn’t load resource',0);
- IF (gError = memFullErr) THEN
- ErrorMsg('No room in heap zone',1)
- ELSE
- ErrorOSErr('');
- CommentWhich;
- ReleaseRsrc(pRsrcPtr);
- EXIT(GetRsrc);
- END;
- END;
- fSize := SizeResource(fHdl);
- END
- ELSE
- BEGIN
- fFlag := kRsrcHdlValid;
- fSize := MaxSizeRsrc(fHdl);
- fLoaded := eNotYet;
- IF gOption[eTrace] THEN
- Trace('No-load get, loaded not yet');
- END;
- IF (pIntIs = Index) THEN
- BEGIN
- GetResInfo(fHdl,fResId,fResType,sName);
- gError := ResError;
- IF (gError <> NoErr) THEN
- BEGIN
- ErrorOSErr('Couldn’t get resource id');
- CommentWhich;
- ReleaseRsrc(pRsrcPtr);
- EXIT(GetRsrc);
- END;
- END;
- IF sResLoad THEN
- BEGIN
- fState := HGetState(fHdl);
- IF ((fResType = 'CODE')
- AND (fResId = 0)) THEN
- BEGIN
- MoveHHi(fHdl);
- HLock (fHdl);
- END
- ELSE
- HNoPurge(fHdl);
- END;
- END;
- IF gOption[eTrace] THEN
- TraceRsrc('Got',pRsrcPtr);
- INC(gCounts.fResources);
- INC(gTotals.fResources);
- END;
- {-------------------------------------------}
- PROCEDURE InitGlobals;
- VAR
- sGetHdl: DialogTHndl;
- sGetSize: Point;
- sPutHdl: DialogTHndl;
- sPutSize: Point;
- sScrnSize: Point;
- BEGIN
- ZeroOutRange(@gAAGlobals,@gZZGlobals);
- gCurrIOBuffer := NewPtr(kIOBufferSize);
- InitRsrc(@gCode0);
- InitRsrc(@gCurrRsrc);
- gEvtMask :=
- everyEvent - (updateMask + activMask);
- GetPort(gGrafPtr);
- gInd := ' ';
-
- sGetHdl :=
- DialogTHndl(GetResource('DLOG',getDlgID));
- IF (sGetHdl = NIL)
- OR (LONGINT(sGetHdl) = -1) THEN
- SetPt(sGetSize,304,104)
- ELSE
- BEGIN
- IF (sGetHdl^ = NIL) THEN
- LoadResource(Handle(sGetHdl));
- sGetSize := sGetHdl^^.boundsRect.botRight;
- ReleaseResource(Handle(sGetHdl));
- END;
-
- sPutHdl :=
- DialogTHndl(GetResource('DLOG',putDlgID));
- IF (sPutHdl = NIL)
- OR (LONGINT(sPutHdl) = -1) THEN
- SetPt(sPutSize,348,136)
- ELSE
- BEGIN
- IF (sPutHdl^ = NIL) THEN
- LoadResource(Handle(sPutHdl));
- sPutSize := sPutHdl^^.boundsRect.botRight;
- ReleaseResource(Handle(sPutHdl));
- END;
-
- WITH gGrafPtr^.portBits.bounds DO
- BEGIN
- sScrnSize.h := right-left;
- sScrnSize.v := bottom-top;
- END;
- gSFGetPt.h := (sScrnSize.h-sGetSize.h) DIV 2;
- gSFGetPt.v := (sScrnSize.v-sGetSize.v) DIV 2;
- gSFPutPt.h := (sScrnSize.h-sPutSize.h) DIV 2;
- gSFPutPt.v := (sScrnSize.v-sPutSize.v) DIV 2;
- END;
- {-------------------------------------------}
- PROCEDURE InitRsrc
- (pRsrcPtr: TRsrcPtr);
- BEGIN
- ZeroOut(Ptr(pRsrcPtr),SIZEOF(TRsrcRec));
- pRsrcPtr^.fFlag := kRsrcIsInitd;
- END;
- {-------------------------------------------}
- FUNCTION JTEIsValid
- (pJTEPtr: TJTEPtr)
- : BOOLEAN;
- VAR
- sCode: TRsrcRec;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('JTEIsValid');
- JTEIsValid := FALSE;
- WITH pJTEPtr^, sCode DO
- BEGIN
- InitRsrc(@sCode);
- SetResLoad(FALSE);
- GetRsrc(@sCode,'CODE',fSegId,ResId);
- SetResLoad(TRUE);
- IF (fFlag <> kRsrcHdlValid) THEN
- EXIT(JTEIsValid);
- JTEIsValid :=
- (fSkip3F3C = $3F3C) AND
- (fSegId > 0) AND
- (fSkipA9F0 = -22032) AND { $A9F0 }
- (fSize > 0);
- ReleaseRsrc(@sCode);
- END;
- END;
- {-------------------------------------------}
- PROCEDURE ListCounts
- (pPtr: TCountsPtr);
- BEGIN
- IF gOption[eTrace] THEN
- Trace('CountsListing');
- WITH pPtr^ DO
- BEGIN
- WryteLn ('Files:');
- WryteNbr(fFiles, 6);
- WryteLn (' processed');
- WryteNbr(fExamined,6);
- WryteLn (' examined');
- WryteNbr(fDeleted, 6);
- WryteLn (' deleted');
- WryteLn ('Resources:');
- WryteNbr(fResources,6);
- WryteLn (' processed');
- WryteNbr(fInfected, 6);
- WryteLn (' infected');
- WryteNbr(fRemoved, 6);
- WryteLn (' removed');
- Wryte ('Currently available memory is ');
- WryteNbr(MemAvail DIV 1024,1);
- WryteLn ('K.');
- PauseBriefly;
- END;
- END;
- {-------------------------------------------}
- PROCEDURE LookForKnownViruses;
- VAR
- sWeUsedToBeInfected: BOOLEAN;
- {--------------------}
- PROCEDURE Get1stCode;
- BEGIN
- WITH TJTHdl(gCode0.fHdl)^^.fJTEntry[1] DO
- BEGIN
- GetRsrc(@gCurrRsrc,'CODE',fSegId,ResId);
- IF (gCurrRsrc.fFlag<>kRsrcHdlValid) THEN
- BEGIN
- ErrorInfected('Couldn’t get 1st CODE');
- InitRsrc(@gCurrRsrc);
- EXIT(LookForKnownViruses);
- END;
- END;
- END;
- {--------------------}
- BEGIN
- IF gOption[eTrace] THEN
- Trace('LookForKnownViruses');
- sWeUsedToBeInfected := FALSE;
- Get1stCode;
- WITH gCurrRsrc DO
- BEGIN
- LookForVirus_nVIR;
- IF fInfected THEN
- BEGIN
- CountInfected;
- IF fKnown AND (fSize = 372) THEN
- ErrorInfected('nVIR 372 virus')
- ELSE IF fKnown AND (fSize = 422) THEN
- ErrorInfected('nVIR 422 virus')
- ELSE
- BEGIN
- ErrorInfected('New nVIR virus!');
- gFgPrTitle := '';
- CommentFgPrRsrc(@gCurrRsrc);
- END;
- IF Disinfected_nVIR THEN
- sWeUsedToBeInfected := TRUE;
- Get1stCode;
- END;
- LookForVirus_Scores;
- IF fKnown AND fInfected THEN
- BEGIN
- CountInfected;
- ErrorInfected('Scores virus');
- IF Disinfected_Scores THEN
- sWeUsedToBeInfected := TRUE;
- END
- ELSE
- ReleaseRsrc(@gCurrRsrc);
- END;
- IF sWeUsedToBeInfected THEN
- LookForKnownViruses;
- END;
- {-------------------------------------------}
- PROCEDURE PatrolBegins;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('PatrolBegins');
- WryteEoln;
- WryteLn('*******************************');
- ZeroOut(@gCounts,SIZEOF(TCountsRec));
- GetDateTime(gSecsBegins);
- END;
- {-------------------------------------------}
- PROCEDURE PatrolEnds;
- VAR
- sMins: INTEGER;
- sSecs: INTEGER;
- BEGIN
- GetDateTime(gSecsEnds);
- sSecs := gSecsEnds - gSecsBegins;
- sMins := sSecs DIV 60;
- sSecs := sSecs - (sMins * 60);
- WryteEoln;
- WryteLn('*******************************');
- WryteEoln;
- Wryte ('End of patrol that took ');
- WryteNbr(sMins,1);
- WryteChar(':');
- IF (sSecs < 10) THEN
- BEGIN
- WryteChar('0');
- WryteNbr (sSecs,1);
- END
- ELSE
- WryteNbr (sSecs,2);
- WryteEoln;
- ListCounts(@gCounts);
- END;
- {-------------------------------------------}
- PROCEDURE PauseBriefly;
- VAR
- sTicks: LONGINT;
- BEGIN
- Delay(120,sTicks);
- END;
- {-------------------------------------------}
- PROCEDURE ProcessCodes;
- VAR
- i: INTEGER;
- sNbrEntries: INTEGER;
- sPrevId: INTEGER;
- sWeirdCode0: BOOLEAN;
- {------------------------}
- PROCEDURE CommentWhere;
- BEGIN
- CommentBegins;
- Wryte ('At entry ');
- WryteNbr(i,1);
- WryteEoln;
- END;
- {------------------------}
- BEGIN
- IF gOption[eTrace] THEN
- Trace('ProcessCodes');
- GetRsrc(@gCode0,'CODE',0,ResId);
- IF (gCode0.fFlag <> kRsrcHdlValid) THEN
- BEGIN
- ErrorMsg('Code rsrcs without CODE 0',1);
- EXIT(ProcessCodes);
- END;
- IF NOT(Code0IsValid) THEN
- BEGIN
- ErrorMsg('Unexpected CODE 0 values',1);
- ReleaseRsrc(@gCode0);
- EXIT(ProcessCodes);
- END;
- LookForKnownViruses;
- WITH TJTHdl(gCode0.fHdl)^^ DO
- BEGIN
- sNbrEntries := fNbrBytesInTable DIV 8;
- sPrevId := 1;
- sWeirdCode0 :=
- (COPY(gCurrFilename,1,9)='Red Ryder') OR
- (COPY(gCurrFilename,1,6)='Canvas' ) OR
- (COPY(gCurrFilename,1,9)='PageMaker');
- FOR i := 1 TO sNbrEntries DO
- WITH fJTEntry[i] DO
- BEGIN
- IF (fSkip3F3C = $3F3C)
- AND (fSegId = sPrevId)
- AND (fSkipA9F0 = -22032) THEN
- CYCLE;
- AbortPatrolIfCmdPeriodPressed;
- IF gAbortPatrol THEN
- LEAVE;
- IF NOT(JTEIsValid(@fJTEntry[i])) THEN
- BEGIN
- ErrorMsg('CODE 0 has invalid JTE',1);
- CommentWhere;
- LEAVE;
- END;
- IF sWeirdCode0 THEN
- BEGIN
- sPrevId := fSegId;
- CYCLE;
- END;
- IF (fSegId < sPrevId) THEN
- BEGIN
- ErrorMsg('JT not ascending',1);
- CommentWhere;
- LEAVE;
- END;
- INC(sPrevId);
- IF (fSegId = sPrevId) THEN
- CYCLE;
- ErrorMsg('JT skips ResId',1);
- CommentWhere;
- LEAVE;
- END;
- END;
- ReleaseRsrc(@gCode0);
- END;
- {-------------------------------------------}
- PROCEDURE ProcessFile;
- VAR
- sSaveC1T: INTEGER;
- {----------------------------}
- PROCEDURE ExitIfCantReadFork;
- BEGIN
- IF (gError <> NoErr) THEN
- BEGIN
- IF (gError = eofErr) THEN
- { no resource fork }
- ELSE IF (gError = fnfErr) THEN
- ErrorMsg('File not found',1)
- ELSE IF (gError = nsvErr) THEN
- ErrorMsg('No such volume',1)
- ELSE IF (gError = opWrErr) THEN
- ErrorMsg(CONCAT('Already in use. ',
- '(Don’t use under MultiFinder!)'),1)
- ELSE
- ErrorOSErr('Couldn’t open file');
- gError := NoErr;
- EXIT(ProcessFile);
- END;
- END;
- {----------------------------}
- BEGIN
- IF gOption[eTrace] THEN
- Trace('ProcessFile');
- AbortPatrolIfCmdPeriodPressed;
- IF gAbortPatrol THEN
- EXIT(ProcessFile);
- INC(gCounts.fFiles);
- INC(gTotals.fFiles);
- gInfected := FALSE;
- gInfectedWritten := FALSE;
- gReportFlags.fWroteFilename := FALSE;
- gScreenFlags.fWroteFilename := FALSE;
- IF gOption[eLList] THEN
- WryteFilename
- ELSE
- WryteFilenameToScreenOnlyForNow;
- IF (LENGTH(gCurrFilename) > 0) THEN
- IF (gCurrFilename[1] = '.') THEN
- BEGIN
- ErrorMsg('Filename begins with “.”',1);
- EXIT(ProcessFile);
- END;
- IF gActiveSelf AND NOT(kProcessSelf) THEN
- EXIT(ProcessFile);
- gCurrEOF := -1;
- gError := FSOpen(gCurrFilename,gCurrWDRefNum,
- gCurrRefNum);
- ExitIfCantReadFork;
- gError := GetEOF(gCurrRefNum,gCurrEOF);
- IF (gError = NoErr) THEN
- BEGIN
- WITH gCurrFInfo DO
- IF (COPY(gCurrFilename,1,7)='MacsBug')
- OR (fdType = 'RELB')
- OR (fdType = 'OBJ ') THEN
- IF NOT(KnownDataFork) THEN
- CommentFgPrData;
- gError := FSClose(gCurrRefNum);
- IF (gError <> NoErr) THEN
- ErrorOSErr('Couldn’t close data fork');
- END
- ELSE
- ErrorOSErr('Couldn’t GetEOF');
- IF gActiveSelf THEN
- BEGIN
- gCurrRefNum := TWordPtr(kCurApRefNum)^;
- gError := NoErr;
- END
- ELSE IF gActiveSys THEN
- BEGIN
- gCurrRefNum := TWordPtr(kSysMap)^;
- gError := NoErr;
- END
- ELSE
- BEGIN
- SetResLoad(FALSE);
- gCurrRefNum := OpenRFPerm(gCurrFilename,
- gCurrWDRefNum,
- fsRdWrPerm);
- gError := ResError;
- SetResLoad(TRUE);
- ExitIfCantReadFork;
- END;
- IF (gCurrRefNum <> CurResFile) THEN
- BEGIN
- UseResFile(gCurrRefNum);
- gError := ResError;
- IF (gError <> NoErr) THEN
- BEGIN
- ErrorOSErr('Couldn’t use resource fork');
- gError := NoErr;
- EXIT(ProcessFile);
- END;
- END;
- INC(gCounts.fExamined);
- INC(gTotals.fExamined);
- IF (Count1Resources('CODE') > 0) THEN
- ProcessCodes;
- gFgPrTitle := 'Unknown Resource(s):';
- ProcessRsrcs('ADBS',@Process_ADBS);
- ProcessRsrcs('CACH',@Process_CACH);
- ProcessRsrcs('CDEF',@Process_CDEF);
- ProcessRsrcs('DATA',@Process_DATA);
- ProcessRsrcs('DRVR',@Process_DRVR);
- ProcessRsrcs('DSAT',@Process_DSAT);
- ProcessRsrcs('FKEY',@Process_FKEY);
- ProcessRsrcs('FMTR',@Process_FMTR);
- ProcessRsrcs('INIT',@Process_INIT);
- ProcessRsrcs('LDEF',@Process_LDEF);
- ProcessRsrcs('MBDF',@Process_MBDF);
- ProcessRsrcs('MDEF',@Process_MDEF);
- ProcessRsrcs('MMAP',@Process_MMAP);
- ProcessRsrcs('NBPC',@Process_NBPC);
- ProcessRsrcs('PACK',@Process_PACK);
- ProcessRsrcs('PDEF',@Process_PDEF);
- ProcessRsrcs('PTCH',@Process_PTCH);
- ProcessRsrcs('ROv#',@Process_ROvList);
- ProcessRsrcs('ROvr',@Process_ROvr);
- ProcessRsrcs('SERD',@Process_SERD);
- ProcessRsrcs('WDEF',@Process_WDEF);
- ProcessRsrcs('XCMD',@Process_XCMD);
- ProcessRsrcs('XFCN',@Process_XFCN);
- ProcessRsrcs('atpl',@Process_atpl);
- ProcessRsrcs('boot',@Process_boot);
- ProcessRsrcs('cdev',@Process_cdev);
- ProcessRsrcs('mppc',@Process_mppc);
- ProcessRsrcs('snth',@Process_snth);
- ProcessRsrcs('view',@Process_view);
- IF gOption[eFgPr] THEN
- BEGIN
- gFgPrTitle := 'Fingerprint(s):';
- ProcessRsrcs('ADBS',@ProcessCurrRsrc);
- ProcessRsrcs('CACH',@ProcessCurrRsrc);
- ProcessRsrcs('CDEF',@ProcessCurrRsrc);
- IF gOption[eFgPrC] THEN
- ProcessRsrcs('CODE',@ProcessCurrRsrc);
- ProcessRsrcs('DATA',@ProcessCurrRsrc);
- ProcessRsrcs('DRVR',@ProcessCurrRsrc);
- ProcessRsrcs('DSAT',@ProcessCurrRsrc);
- ProcessRsrcs('FKEY',@ProcessCurrRsrc);
- ProcessRsrcs('FMTR',@ProcessCurrRsrc);
- ProcessRsrcs('INIT',@ProcessCurrRsrc);
- ProcessRsrcs('LDEF',@ProcessCurrRsrc);
- ProcessRsrcs('MBDF',@ProcessCurrRsrc);
- ProcessRsrcs('MDEF',@ProcessCurrRsrc);
- ProcessRsrcs('MMAP',@ProcessCurrRsrc);
- ProcessRsrcs('NBPC',@ProcessCurrRsrc);
- ProcessRsrcs('PACK',@ProcessCurrRsrc);
- ProcessRsrcs('PDEF',@ProcessCurrRsrc);
- ProcessRsrcs('PTCH',@ProcessCurrRsrc);
- ProcessRsrcs('ROv#',@ProcessCurrRsrc);
- ProcessRsrcs('ROvr',@ProcessCurrRsrc);
- ProcessRsrcs('SERD',@ProcessCurrRsrc);
- ProcessRsrcs('WDEF',@ProcessCurrRsrc);
- ProcessRsrcs('XCMD',@ProcessCurrRsrc);
- ProcessRsrcs('XFCN',@ProcessCurrRsrc);
- ProcessRsrcs('atpl',@ProcessCurrRsrc);
- ProcessRsrcs('boot',@ProcessCurrRsrc);
- ProcessRsrcs('cdev',@ProcessCurrRsrc);
- ProcessRsrcs('mppc',@ProcessCurrRsrc);
- ProcessRsrcs('snth',@ProcessCurrRsrc);
- ProcessRsrcs('view',@ProcessCurrRsrc);
- ProcessRsrcs('nVIR',@ProcessCurrRsrc);
- END;
- IF gActiveSelf OR gActiveSys THEN
- EXIT(ProcessFile);
- sSaveC1T := Count1Types;
- CloseResFile(gCurrRefNum);
- IF NOT(gInfected) THEN
- EXIT(ProcessFile);
- WITH gCurrFInfo DO
- BEGIN
- IF ((gCurrFilename = 'Note Pad File')
- OR (gCurrFilename = 'Scrapbook File'))
- AND (fdCreator = 'ZSYS')
- AND gOption[eRmVir] THEN
- BEGIN
- fdType := 'ZSYS';
- fdCreator := 'MACS';
- fdFlags := 4096;
- gError := SetFInfo(gCurrFilename,
- gCurrWDRefNum,
- gCurrFInfo);
- IF (gError = NoErr) THEN
- ErrorMsg('Reset to system document',0)
- ELSE
- ErrorOSErr('FInfo not reset');
- EXIT(ProcessFile);
- END;
- END;
- IF (gCurrEOF <> 0) THEN
- BEGIN
- ErrorMsg('File still has data fork',0);
- ErrorMsg('File not deleted',1);
- EXIT(ProcessFile);
- END;
- IF (sSaveC1T <> 0) THEN
- BEGIN
- ErrorMsg('File still has resources',0);
- ErrorMsg('File not deleted',1);
- EXIT(ProcessFile);
- END;
- ErrorMsg('File emptied',0);
- gError :=
- FSDelete(gCurrFilename,gCurrWDRefNum);
- IF (gError = NoErr) THEN
- BEGIN
- gCurrFileDeleted := TRUE;
- INC(gCounts.fDeleted);
- INC(gTotals.fDeleted);
- ErrorMsg('File deleted',1);
- END
- ELSE
- ErrorOSErr('File not deleted');
- END;
- {-------------------------------------------}
- PROCEDURE ProcessRsrcs
- (pResType: ResType;
- pProcPtr: ProcPtr);
- VAR
- i: INTEGER;
- sIdx: INTEGER;
- BEGIN
- IF gOption[eTrace] THEN
- Trace('ProcessRsrcs');
- WITH gCurrRsrc DO
- BEGIN
- sIdx := 1;
- FOR i := 1 TO Count1Resources(pResType) DO
- BEGIN
- AbortPatrolIfCmdPeriodPressed;
- IF gAbortPatrol THEN
- LEAVE;
- GetRsrc(@gCurrRsrc,pResType,sIdx,Index);
- IF (fFlag <> kRsrcHdlValid) THEN
- BEGIN
- INC(sIdx);
- CYCLE;
- END;
- CallProcPtr(pProcPtr);
- IF fInfected THEN
- BEGIN
- CountInfected;
- ErrorInfected('');
- CommentRsrcBegins(@gCurrRsrc);
- WryteLn(' is an infection');
- IF RemovedRsrc(@gCurrRsrc) THEN
- BEGIN
- ErrorMsg('Removed',0);
- CYCLE;
- END;
- ErrorMsg('Not removed',1);
- INC(sIdx);
- CYCLE;
- END;
- IF NOT(fKnown) THEN
- CommentFgPrRsrc(@gCurrRsrc);
- ReleaseRsrc(@gCurrRsrc);
- INC(sIdx);
- END;
- END;
- END;
- {-------------------------------------------}
- PROCEDURE ReleaseRsrc
- (pRsrcPtr: TRsrcPtr);
- BEGIN
- WITH pRsrcPtr^ DO
- BEGIN
- IF (fFlag <> kRsrcHdlValid) THEN
- BEGIN
- ErrorMsg('Error using ReleaseRsrc',4);
- AwaitKeypress;
- ExitSecurityPatrol;
- END;
- IF gOption[eTrace] THEN
- TraceRsrc('About to release',pRsrcPtr);
- IF (gActiveSelf OR gActiveSys) THEN
- IF gOption[eTrace] THEN
- Trace('Not Released')
- ELSE
- ELSE
- BEGIN
- HSetState(fHdl,fState);
- ReleaseResource(fHdl);
- IF gOption[eTrace] THEN
- Trace('Released');
- END;
- InitRsrc(pRsrcPtr);
- END;
- END;
- {-------------------------------------------}
- FUNCTION RemovedRsrc
- (pRsrcPtr: TRsrcPtr)
- : BOOLEAN;
- VAR
- sBits0and7:LONGINT;
- {--------------------}
- PROCEDURE ExitIfError
- (pStr: Str255);
- BEGIN
- gError := ResError;
- IF (gError <> NoErr) THEN
- BEGIN
- ErrorMsg(pStr,0);
- IF (gError = wPrErr) THEN
- ErrorMsg('Disk is locked',0)
- ELSE
- ErrorOSErr('');
- CommentRsrcBegins(pRsrcPtr);
- WryteLn(' not removed');
- ReleaseRsrc(pRsrcPtr);
- EXIT(RemovedRsrc);
- END;
- END;
- {--------------------}
- BEGIN
- RemovedRsrc := FALSE;
- IF gOption[eTrace] THEN
- Trace('RemovedRsrc');
- AbortPatrolIfCmdPeriodPressed;
- IF gAbortPatrol
- OR NOT(gOption[eRmVir]) THEN
- BEGIN
- ReleaseRsrc(pRsrcPtr);
- EXIT(RemovedRsrc);
- END;
- WITH pRsrcPtr^ DO
- BEGIN
- IF (fFlag <> kRsrcHdlValid) THEN
- BEGIN
- ErrorMsg('Error using RemovedRsrc',4);
- AwaitKeypress;
- ExitSecurityPatrol;
- END;
- IF gOption[eTrace] THEN
- BEGIN
- TraceRsrc('About to remove',pRsrcPtr);
- AbortPatrolIfCmdPeriodPressed;
- IF gAbortPatrol THEN
- EXIT(RemovedRsrc);
- END;
- IF NOT(fInfected) THEN
- BEGIN
- ErrorMsg('Tried to remove uninfected',4);
- AwaitKeypress;
- ExitSecurityPatrol;
- END;
- IF kZeroOutVirs AND (fHdl^ <> NIL) THEN
- BEGIN
- ZeroOut(fHdl^,fSize);
- ChangedResource(fHdl);
- gError := ResError;
- IF (gError = NoErr) THEN
- BEGIN
- WriteResource(fHdl);
- gError := ResError;
- IF (gError <> NoErr) THEN
- ErrorOSErr('Couldn’t WriteResource');
- END
- ELSE
- ErrorOSErr('Couldn’t ChangedResource');
- END;
- sBits0and7 := BAnd(fResAttrs,$81);
- SetResAttrs(fHdl,LoWord(sBits0and7));
- RmveResource(fHdl);
- ExitIfError('Couldn’t remove resource');
- UpdateResFile(gCurrRefNum);
- ExitIfError('Couldn’t update res file');
- DisposHandle(fHdl);
- InitRsrc(pRsrcPtr);
- RemovedRsrc := TRUE;
- IF gOption[eTrace] THEN
- Trace('RemovedRsrc successful');
- END;
- INC(gCounts.fRemoved);
- INC(gTotals.fRemoved);
- END;
- {-------------------------------------------}
- PROCEDURE ShortHexDump
- (pPtr: Ptr;
- pNbrBytes: SignedByte);
- VAR
- i: INTEGER;
- sCh1,sCh2: LONGINT;
- sDigit: LONGINT;
- sIdx: Ptr;
- BEGIN
- sIdx := pPtr;
- FOR i := 1 TO pNbrBytes DO
- BEGIN
- sDigit := ORD4(sIdx^);
- sCh1 := BSR(BAnd(sDigit,$F0),4);
- sCh2 := BAnd(sDigit,$0F);
- IF sCh1 > 9 THEN
- WryteChar(CHR(sCh1 + $37))
- ELSE
- WryteChar(CHR(sCh1 + $30));
- IF sCh2 > 9 THEN
- WryteChar(CHR(sCh2 + $37))
- ELSE
- WryteChar(CHR(sCh2 + $30));
- INC(LONGINT(sIdx));
- END;
- END;
- {-------------------------------------------}
- PROCEDURE Trace
- (pStr: Str255);
- BEGIN
- ErrorBegins(pStr);
- ErrorEnds(0);
- END;
- {-------------------------------------------}
- PROCEDURE TraceNbr
- (pStr: Str255;
- pNbr: LONGINT);
- BEGIN
- ErrorBegins(pStr);
- WryteNbr(pNbr,1);
- ErrorEnds(0);
- END;
- {-------------------------------------------}
- PROCEDURE TraceRsrc
- (pStr: Str255;
- pRsrcPtr: TRsrcPtr);
- BEGIN
- ErrorBegins(pStr);
- WITH pRsrcPtr^ DO
- BEGIN
- WryteChar(' ');
- WryteType(fResType);
- WryteNbr (fResId,7);
- END;
- ErrorEnds(0);
- END;
- {-------------------------------------------}
- PROCEDURE ZeroOut
- (pStart: Ptr;
- pCount: Size);
- VAR
- i: INTEGER;
- sIdx: Ptr;
- BEGIN
- sIdx := pStart;
- FOR i := 1 TO pCount DO
- BEGIN
- sIdx^ := 0;
- INC(LONGINT(sIdx));
- END;
- END;
- {-------------------------------------------}
- PROCEDURE ZeroOutRange
- (p1: Ptr;
- p2: Ptr);
- VAR
- i: INTEGER;
- sIdx: Ptr;
- BEGIN
- IF (ORD4(p1) < ORD4(p2)) THEN
- sIdx := p1
- ELSE
- sIdx := p2;
- FOR i := 1 TO ABS(ORD4(p2)-ORD4(p1))+1 DO
- BEGIN
- sIdx^ := 0;
- INC(LONGINT(sIdx));
- END;
- END;
- {*******************************************}
- END.